#include "InputLine.h"
#include <iostream>

//Default Constructor
InputLine::InputLine(){}

//Destructor
InputLine::~InputLine(){}

//public funcs
vector<Token> InputLine::TokenizeLine(int line_id, const string& line)
{
	Token t;
	vector<Token> ret_vector;
	vector<string> v_words = divideStr(line);
	vector<string>::iterator it_1word;
	vector<Token> v_token;
	vector<Token>::iterator it_v_token_begin;
	vector<Token>::iterator it_v_token_end;
	vector<Token>::iterator it_ret_vector;
	string str;
	for(it_1word = v_words.begin() ; it_1word != v_words.end() ; it_1word++)
	{
		v_token = divideWordToToken(line_id, it_1word->c_str());
		//init iterstors for inserting to the ret_vector
		it_ret_vector = ret_vector.end();
		it_v_token_begin = v_token.begin();
		it_v_token_end = v_token.end();
		//insert to ret_vector
		ret_vector.insert(it_ret_vector, it_v_token_begin, it_v_token_end);
	}
	return ret_vector;
}




vector<string> InputLine::divideStr(const string& str)
{
	string str_with_no_tabs = elimanateTabs(str);
	vector<string> ret_vector;
	unsigned int end = 0;
	unsigned int start = 0;
	string tmp_token;
	string tmp_str = str_with_no_tabs;
	while(end != string::npos)
	{
		end = tmp_str.find_first_of(" ");
		tmp_token = tmp_str.substr(start, end);
		ret_vector.push_back(tmp_token);
		tmp_str = tmp_str.substr(end+1);
	}
	return ret_vector;
}

vector<Token> InputLine::divideWordToToken(int line_id, const string& word)
{
	vector<Token> ret_vector;
	vector<string>::iterator vec_str_it;
	bool is_letter = false;
	bool is_sign = false;
	unsigned int len = word.length();
	for(unsigned int i = 0 ; i < len ; i++)
	{
		is_letter = false;
		is_sign =  false;
		string letter_str;
		//it's a Predefined || Key words  || Identifiers
		while(word[i] >= 'a' && word[i] <= 'z' || word[i] >= 'A' && word[i] <= 'Z' || word[i] >= '0' && word[i] <= '9') 
		{
			letter_str.push_back(word[i]);
			i++;
			is_letter = true;
		}
		if(is_letter)
		{
			string type = findLettersType(letter_str);
			Token t(line_id, letter_str, type);
			ret_vector.push_back(t);
			i--;
			continue;
		}
		
		// it's Operators || delimiter
		string sign_str;
		if(i != len-1) //it's not the last char
		{
			if(word[i] == '+' && word[i+1] == '+'|| word[i] == '-' && word[i+1] == '-' || word[i] == '-' && word[i+1] == '>' 
				|| word[i] == '=' && word[i+1] == '=' || word[i] == '>' && word[i+1] == '>' || word[i] == '<' && word[i+1] == '<')
			{	//it's a special oprator
				sign_str.push_back(word[i++]);
				sign_str.push_back(word[i]);
				Token t(line_id, sign_str, "operators");
				ret_vector.push_back(t);
				continue;
			}
			else
			{	//it's a regular oprator or delimeter
				sign_str.push_back(word[i]);
				string type = findSignType(sign_str);
				Token t(line_id, sign_str, type);
				ret_vector.push_back(t);
			}
		} 
		else ////it's the last char
		{
			sign_str.push_back(word[i]);
			string type = findSignType(sign_str);
			Token t(line_id, sign_str, type);
			ret_vector.push_back(t);
		}
	} // end for
	return ret_vector;
}


string InputLine::findLettersType(const string& letter_str)
{
	Misc m; //Misc
	string ret_type;
	vector<string>::iterator it;
	for(it = m.predefined.begin() ; it !=m.predefined.end() ; it++)
	{
		if(letter_str.compare(*it) == 0)
		{
			ret_type = "predefined";
			return ret_type;
		}
	}
	
	for(it = m.keywords1.begin() ; it !=m.keywords1.end() ; it++)
	{
		if(letter_str.compare(*it) == 0)
		{
			ret_type = "keywords";
			return ret_type;
		}
	}

	for(it = m.keywords2.begin() ; it !=m.keywords2.end() ; it++)
	{
		if(letter_str.compare(*it) == 0)
		{
			ret_type = "keywords";
			return ret_type;
		}
	}

	ret_type = "Identifiers";
	return ret_type;
}

string InputLine::findSignType(const string& letter_str)
{
	Misc m;
	string ret_type;
	vector<string>::iterator it;
	for(it = m.delimiters.begin() ; it !=m.delimiters.end() ; it++)
	{
		if(letter_str.compare(*it) == 0){
			ret_type = "delimiters";
			return ret_type;
		}
	}
	
	for(it = m.operators.begin() ; it !=m.operators.end() ; it++)
	{
		if(letter_str.compare(*it) == 0)
		{
			ret_type = "operators";
			return ret_type;
		}
	}

	ret_type = "error_type"; 
	return ret_type;
}

string InputLine::elimanateTabs(const string &str)
{
	string ret_str;
	ret_str = str;
	ret_str.erase(remove(ret_str.begin(), ret_str.end(), '\t'), ret_str.end());
	return ret_str;
}